﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace XenAppServices.ServiceLibrary.XenApp6
{
    public class XAServicesService : IXAServicesService
    {
        /// <summary>
        /// Get XenApp sessions for the specified user
        /// </summary>
        /// <param name="username">Username</param>
        /// <returns></returns>
        public System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession> GetSessionsByUsername(string currentUsername)
        {
            if (!currentUsername.Contains("\\"))
            {
                // need the username in the form of domain\username.
                // If no domain is specified, use the doamin of the Windows service account
                currentUsername = System.Environment.UserDomainName + "\\" + currentUsername;
            }

            System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession> sessions =
                new System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession>();

            try
            {
               PowerShell psCmd = PowerShell.Create();

                PSSnapInException psEx;
                psCmd.Runspace.RunspaceConfiguration.AddPSSnapIn("Citrix.XenApp.Commands", out psEx);

                foreach (var _session in psCmd.AddCommand("Get-XASession").AddParameter("Account", currentUsername).Invoke())
                {
                    XenAppServices.Classes.XASession session = new XenAppServices.Classes.XASession();

                    session.Username = _session.Properties["AccountName"].Value.ToString();
                    session.Application = _session.Properties["BrowserName"].Value.ToString();
                    session.ClientName = _session.Properties["ClientName"].Value.ToString();

                    if(_session.Properties["LogOnTime"].Value != null)
                        session.LogonTime = (DateTime)_session.Properties["LogOnTime"].Value;

                    session.ServerName = _session.Properties["ServerName"].Value.ToString();
                    
                    if(_session.Properties["SessionId"].Value != null)
                        session.SessionID = (Int32)_session.Properties["SessionId"].Value;

                    session.SessionName = _session.Properties["SessionName"].Value.ToString();
                    
                    if(_session.Properties["State"].Value != null)
                        session.SessionState = getSessionState(_session.Properties["State"].Value.ToString());

                    sessions.Add(session);
                }

            }
            catch (ApplicationException ex)
            {
                throw new FaultException<ApplicationException>(
                        ex,
                        new FaultReason(ex.Message),
                        new FaultCode("Sender")
                    );
            }

            return sessions;
        }

        /// <summary>
        /// Get XenApp sessions on a server
        /// </summary>
        /// <param name="serverName">Server</param>
        /// <returns></returns>
        public System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession> GetSessionsByServername(string serverName)
        {
            System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession> sessions =
                new System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession>();

            try
            {
                PowerShell psCmd = PowerShell.Create();

                PSSnapInException psEx;
                psCmd.Runspace.RunspaceConfiguration.AddPSSnapIn("Citrix.XenApp.Commands", out psEx);

                foreach (var _session in psCmd.AddCommand("Get-XASession").AddParameter("ServerName", serverName).Invoke())
                {
                    XenAppServices.Classes.XASession session = new XenAppServices.Classes.XASession();

                    session.Username = _session.Properties["AccountName"].Value.ToString();
                    session.Application = _session.Properties["BrowserName"].Value.ToString();
                    session.ClientName = _session.Properties["ClientName"].Value.ToString();

                    if (_session.Properties["LogOnTime"].Value != null)
                        session.LogonTime = (DateTime)_session.Properties["LogOnTime"].Value;

                    session.ServerName = _session.Properties["ServerName"].Value.ToString();

                    if (_session.Properties["SessionId"].Value != null)
                        session.SessionID = (Int32)_session.Properties["SessionId"].Value;

                    session.SessionName = _session.Properties["SessionName"].Value.ToString();

                    if (_session.Properties["State"].Value != null)
                        session.SessionState = getSessionState(_session.Properties["State"].Value.ToString());

                    sessions.Add(session);
                }

            }
            catch (ApplicationException ex)
            {
                throw new FaultException<ApplicationException>(
                        ex,
                        new FaultReason(ex.Message),
                        new FaultCode("Sender")
                    );
            }

            return sessions;
        }

        /// <summary>
        /// Logs off a session
        /// </summary>
        /// <param name="serverName">Server name where sessions resides</param>
        /// <param name="sessionName">Name of the session</param>
        /// <param name="sessionId">ID of the session</param>
        public void LogoffSession(string serverName, string sessionName, int sessionId)
        {
            try
            {
                PowerShell psCmd = PowerShell.Create();

                PSSnapInException psEx;
                psCmd.Runspace.RunspaceConfiguration.AddPSSnapIn("Citrix.XenApp.Commands", out psEx);

                psCmd.AddCommand("Stop-XASession").AddParameter("ServerName", serverName).AddParameter("SessionId", sessionId).Invoke(); ;

            }
            catch (ApplicationException ex)
            {
                throw new FaultException<ApplicationException>(
                        ex,
                        new FaultReason(ex.Message),
                        new FaultCode("Sender")
                    );
            }
        }

        /// <summary>
        /// Returns the current version of the service
        /// </summary>
        /// <returns></returns>
        public string GetVersion()
        {
            Version ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;

            return string.Format("{0}.{1}", ver.Major, ver.Minor);
        }

        /// <summary>
        /// Returns a collection of XenApp applications in a farm
        /// </summary>
        /// <returns>System.Collections.ObjectModel.Collection<XenAppServices.Classes.XAApplication></returns>
        public System.Collections.ObjectModel.Collection<XenAppServices.Classes.XAApplication> GetFarmApplications()
        {
            System.Collections.ObjectModel.Collection<XenAppServices.Classes.XAApplication> applications =
                new System.Collections.ObjectModel.Collection<Classes.XAApplication>();

            return applications;
        }
        
        private XenAppServices.Classes.SessionState getSessionState(string state)
        {
            XenAppServices.Classes.SessionState sessionState = XenAppServices.Classes.SessionState.Unknown;

            switch (state.ToLower())
            {
                case "active":
                    sessionState = XenAppServices.Classes.SessionState.Active;
                    break;
                case "connected":
                    sessionState = XenAppServices.Classes.SessionState.Connected;
                    break;
                case "connecting":
                    sessionState = XenAppServices.Classes.SessionState.Connecting;
                    break;
                case "disconnected":
                    sessionState = XenAppServices.Classes.SessionState.Disconnected;
                    break;
                case "down":
                    sessionState = XenAppServices.Classes.SessionState.Down;
                    break;
                case "idle":
                    sessionState = XenAppServices.Classes.SessionState.Idle;
                    break;
                case "init":
                    sessionState = XenAppServices.Classes.SessionState.Init;
                    break;
                case "listining":
                    sessionState = XenAppServices.Classes.SessionState.Listening;
                    break;
                case "resetting":
                    sessionState = XenAppServices.Classes.SessionState.Resetting;
                    break;
                case "shadowing":
                    sessionState = XenAppServices.Classes.SessionState.Shadowing;
                    break;
                case "unknown":
                    sessionState = XenAppServices.Classes.SessionState.Unknown;
                    break;
            }

            return sessionState;
        }
    }
}
